﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BoringTodo.Extensions;

namespace BoringTodo
{
    /// <summary>
    /// 提供文件操作相关的工具方法
    /// </summary>
    public static class FileUtils
    {
        // 重试次数和等待时间配置
        private const int MaxRetries = 3;
        private const int RetryDelayMilliseconds = 200;

        /// <summary>
        /// 读取文件内容，如果文件不存在则返回null
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns>文件内容或null</returns>
        public static string ReadFileContent(string path)
        {
            if (!File.Exists(path))
            {
                Logger.Log($"文件不存在: {path}", LogLevel.Warning);
                return null;
            }

            try
            {
                return File.ReadAllText(path);
            }
            catch (Exception ex)
            {
                Logger.LogError($"读取文件失败: {path}", ex);
                return null;
            }
        }

        /// <summary>
        /// 读取文件的字节内容，如果文件不存在则返回null
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns>文件字节内容或null</returns>
        public static byte[] ReadFileBytes(string path)
        {
            if (!File.Exists(path))
            {
                Logger.Log($"文件不存在: {path}", LogLevel.Warning);
                return null;
            }

            try
            {
                return File.ReadAllBytes(path);
            }
            catch (Exception ex)
            {
                Logger.LogError($"读取文件失败: {path}", ex);
                return null;
            }
        }

        /// <summary>
        /// 安全地写入内容到文件，确保目录存在
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="content">要写入的内容</param>
        /// <returns>是否写入成功</returns>
        public static bool WriteTextToFile(string path, string content)
        {
            try
            {
                path.SafeWriteAllText(content);
                return true;
            }
            catch (Exception ex)
            {
                Logger.LogError($"写入文件失败: {path}", ex);
                return false;
            }
        }

        /// <summary>
        /// 安全地写入字节内容到文件，确保目录存在
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="bytes">要写入的字节内容</param>
        /// <returns>是否写入成功</returns>
        public static bool WriteBytesToFile(string path, byte[] bytes)
        {
            try
            {
                path.SafeWriteAllBytes(bytes);
                return true;
            }
            catch (Exception ex)
            {
                Logger.LogError($"写入文件失败: {path}", ex);
                return false;
            }
        }

        /// <summary>
        /// 创建目录，如果不存在
        /// </summary>
        /// <param name="path">目录路径</param>
        /// <returns>是否创建成功或已存在</returns>
        public static bool CreateDirectoryIfNotExists(string path)
        {
            try
            {
                path.EnsureDirectoryExists();
                return true;
            }
            catch (Exception ex)
            {
                Logger.LogError($"创建目录失败: {path}", ex);
                return false;
            }
        }

        /// <summary>
        /// 获取唯一的文件路径，确保不会覆盖现有文件
        /// </summary>
        /// <param name="basePath">基本文件路径</param>
        /// <returns>唯一的文件路径</returns>
        public static string GetUniqueFilePath(string basePath)
        {
            return basePath.GetUniqueFilePath();
        }

        /// <summary>
        /// 确保文件名有效，替换无效字符
        /// </summary>
        /// <param name="fileName">原始文件名</param>
        /// <returns>有效的文件名</returns>
        public static string SanitizeFileName(string fileName)
        {
            return fileName.MakeValidFileName();
        }

        /// <summary>
        /// 异步读取文件所有文本内容
        /// </summary>
        public static Task<string> ReadAllTextAsync(string path)
        {
            return Task.Run(() => 
            {
                int retryCount = 0;
                while (true)
                {
                    try
                    {
                        // 使用文件共享选项
                        using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        using (var reader = new StreamReader(fileStream, Encoding.UTF8))
                        {
                            return reader.ReadToEnd();
                        }
                    }
                    catch (IOException ex) when (IsFileLocked(ex) && retryCount < MaxRetries)
                    {
                        // 文件被锁定，等待一段时间后重试
                        retryCount++;
                        System.Threading.Thread.Sleep(RetryDelayMilliseconds * retryCount);
                    }
                    catch (Exception)
                    {
                        // 其他异常直接抛出
                        throw;
                    }
                }
            });
        }

        /// <summary>
        /// 异步写入所有文本到文件
        /// </summary>
        public static Task WriteAllTextAsync(string path, string contents)
        {
            return Task.Run(() => 
            {
                int retryCount = 0;
                while (true)
                {
                    try
                    {
                        // 确保目录存在
                        string directory = Path.GetDirectoryName(path);
                        if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
                        {
                            Directory.CreateDirectory(directory);
                        }

                        // 使用文件流直接写入，并设置适当的文件共享选项
                        using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
                        using (var writer = new StreamWriter(fileStream, Encoding.UTF8))
                        {
                            writer.Write(contents);
                            writer.Flush();
                            return; // 成功写入，退出循环
                        }
                    }
                    catch (IOException ex) when (IsFileLocked(ex) && retryCount < MaxRetries)
                    {
                        // 文件被锁定，等待一段时间后重试
                        retryCount++;
                        Logger.Log($"文件 {path} 被占用，第 {retryCount} 次重试...", LogLevel.Warning);
                        System.Threading.Thread.Sleep(RetryDelayMilliseconds * retryCount);
                    }
                    catch (Exception ex)
                    {
                        // 记录其他异常并抛出
                        Logger.LogError($"写入文件 {path} 失败", ex);
                        throw;
                    }
                }
            });
        }

        /// <summary>
        /// 检查异常是否是由于文件锁定导致的
        /// </summary>
        private static bool IsFileLocked(IOException exception)
        {
            int errorCode = exception.HResult & 0xFFFF;
            return errorCode == 32 || errorCode == 33 || errorCode == 0x20; // 0x20 = 32 = ERROR_SHARING_VIOLATION
        }

        /// <summary>
        /// 异步复制文件
        /// </summary>
        public static Task CopyAsync(string sourceFileName, string destFileName, bool overwrite = false)
        {
            return Task.Run(() => 
            {
                // 创建目标文件夹（如果不存在）
                string destFolder = Path.GetDirectoryName(destFileName);
                if (!Directory.Exists(destFolder))
                {
                    Directory.CreateDirectory(destFolder);
                }
                
                int retryCount = 0;
                while (true)
                {
                    try
                    {
                        File.Copy(sourceFileName, destFileName, overwrite);
                        return; // 成功复制，退出循环
                    }
                    catch (IOException ex) when (IsFileLocked(ex) && retryCount < MaxRetries)
                    {
                        // 文件被锁定，等待一段时间后重试
                        retryCount++;
                        System.Threading.Thread.Sleep(RetryDelayMilliseconds * retryCount);
                    }
                    catch (Exception)
                    {
                        // 其他异常直接抛出
                        throw;
                    }
                }
            });
        }

        /// <summary>
        /// 异步添加文本到文件末尾
        /// </summary>
        public static Task AppendAllTextAsync(string path, string contents)
        {
            return Task.Run(() => 
            {
                int retryCount = 0;
                while (true)
                {
                    try
                    {
                        // 确保目录存在
                        string directory = Path.GetDirectoryName(path);
                        if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory))
                        {
                            Directory.CreateDirectory(directory);
                        }

                        // 使用文件流追加内容，并设置适当的文件共享选项
                        using (var fileStream = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read))
                        using (var writer = new StreamWriter(fileStream, Encoding.UTF8))
                        {
                            writer.Write(contents);
                            writer.Flush();
                            return; // 成功追加，退出循环
                        }
                    }
                    catch (IOException ex) when (IsFileLocked(ex) && retryCount < MaxRetries)
                    {
                        // 文件被锁定，等待一段时间后重试
                        retryCount++;
                        System.Threading.Thread.Sleep(RetryDelayMilliseconds * retryCount);
                    }
                    catch (Exception)
                    {
                        // 其他异常直接抛出
                        throw;
                    }
                }
            });
        }
        
        /// <summary>
        /// 异步创建目录
        /// </summary>
        public static Task CreateDirectoryAsync(string path)
        {
            return Task.Run(() => 
            {
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
            });
        }
        
        /// <summary>
        /// 异步删除文件，带有额外的异常处理
        /// </summary>
        public static Task DeleteFileAsync(string path)
        {
            return Task.Run(() => 
            {
                try
                {
                    // 首先检查文件是否存在
                    if (!File.Exists(path))
                    {
                        // 文件不存在，只记录警告信息但不抛出异常
                        Logger.Log($"尝试删除不存在的文件: {path}", LogLevel.Warning);
                        return; // 直接返回，不执行后续删除操作
                    }

                    int retryCount = 0;
                    while (true)
                    {
                        try
                        {
                            // 尝试直接删除文件
                            File.Delete(path);
                            Logger.Log($"成功删除文件: {path}", LogLevel.Info);
                            return; // 成功删除，退出循环
                        }
                        catch (UnauthorizedAccessException)
                        {
                            try
                            {
                                // 重新检查文件是否存在（可能在此期间被其他进程删除）
                                if (!File.Exists(path))
                                {
                                    Logger.Log($"文件已不存在，无需继续删除: {path}", LogLevel.Warning);
                                    return;
                                }

                                // 如果遇到权限问题，尝试移除只读属性后再次删除
                                File.SetAttributes(path, FileAttributes.Normal);
                                File.Delete(path);
                                Logger.Log($"成功删除只读文件: {path}", LogLevel.Info);
                                return;
                            }
                            catch (FileNotFoundException)
                            {
                                // 文件不存在（可能在尝试设置属性前被其他进程删除）
                                Logger.Log($"尝试更改属性时文件已不存在: {path}", LogLevel.Warning);
                                return;
                            }
                            catch (Exception uaEx)
                            {
                                // 记录权限相关错误
                                Logger.LogError($"删除文件 {path} 时出现权限问题: {uaEx.Message}", uaEx);
                                throw;
                            }
                        }
                        catch (IOException ex) when (IsFileLocked(ex) && retryCount < MaxRetries)
                        {
                            // 文件被占用，等待一段时间后重试
                            retryCount++;
                            Logger.Log($"文件 {path} 被占用，第 {retryCount} 次重试删除...", LogLevel.Warning);
                            System.Threading.Thread.Sleep(RetryDelayMilliseconds * retryCount);
                        }
                        catch (FileNotFoundException)
                        {
                            // 文件在尝试删除期间被其他进程删除
                            Logger.Log($"尝试删除时文件已不存在: {path}", LogLevel.Warning);
                            return;
                        }
                        catch (Exception ex)
                        {
                            // 记录其他异常
                            Logger.LogError($"删除文件 {path} 失败: {ex.Message}", ex);
                            throw;
                        }
                    }
                }
                catch (Exception ex)
                {
                    // 捕获任何外部异常
                    Logger.LogError($"删除文件操作遇到未预期的错误: {ex.Message}", ex);
                    throw;
                }
            });
        }
        
        /// <summary>
        /// 检查文件是否存在
        /// </summary>
        public static bool FileExists(string path)
        {
            return File.Exists(path);
        }
        
        /// <summary>
        /// 检查目录是否存在
        /// </summary>
        public static bool DirectoryExists(string path)
        {
            return Directory.Exists(path);
        }
        
        /// <summary>
        /// 获取文件名（不包含路径）
        /// </summary>
        public static string GetFileName(string path)
        {
            return Path.GetFileName(path);
        }
        
        /// <summary>
        /// 获取文件名（不包含路径和扩展名）
        /// </summary>
        public static string GetFileNameWithoutExtension(string path)
        {
            return Path.GetFileNameWithoutExtension(path);
        }
        
        /// <summary>
        /// 异步获取目录中的所有文件
        /// </summary>
        public static Task<string[]> GetFilesAsync(string path, string searchPattern = "*")
        {
            return Task.Run(() => Directory.GetFiles(path, searchPattern));
        }
    }
}
